package com.basker.pisces.springcloud.feign.config;

import java.util.List;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.basker.pisces.springcloud.feign.FeignClientBeanFactoryPostProcessor;
import com.basker.pisces.springcloud.feign.FeignClientBeanProcessor;
import com.basker.pisces.springcloud.feign.fallback.FeignClientFallbackProcessor;
import com.basker.pisces.springcloud.feign.hystrix.FeignHystrixAnnotationProptiesProcessor;
import com.basker.pisces.springcloud.feign.hystrix.HystrixCodingPropertySource;

import feign.Feign;

/**
 * feign和hystrix配置类
 *
 * @author hangwen
 */
@Configuration
@ConditionalOnClass(Feign.class)
public class FeignHystrixConfig implements InitializingBean, EnvironmentAware {

    private Environment environment;

    @Override
    public void afterPropertiesSet() throws Exception {
        enableFeignHystrixIfNessary();
        setDefaultHystrixFallbackSemaphoreMaxConcurrentRequestsIfNessary();
    }

    /**
     * 用于处理所有FeignFactoryBean的工厂处理器
     *
     * @return
     */
    @Bean
    public FeignClientBeanFactoryPostProcessor feignClientBeanFactoryPostProcessor(
            List<FeignClientBeanProcessor> feignClientBeanProcessors) {
        return new FeignClientBeanFactoryPostProcessor(feignClientBeanProcessors);
    }

    /**
     * 设置默认的Fallback
     *
     * @return
     */
    @Bean
    public FeignClientFallbackProcessor feignClientFallbackProcessor() {
        return new FeignClientFallbackProcessor();
    }

    /**
     * 加载接口上配置的hystrix的注解
     *
     * @param hystrixCodingPropertySource
     * @return
     */
    @Bean
    public FeignHystrixAnnotationProptiesProcessor feignHystrixAnnotationProptiesProcessor(
            HystrixCodingPropertySource hystrixCodingPropertySource) {
        return new FeignHystrixAnnotationProptiesProcessor(hystrixCodingPropertySource);
    }

    /**
     * 通过代码设置的hystrix属性源
     *
     * @return
     */
    @Bean
    public HystrixCodingPropertySource hystrixCodingPropertySource() {
        return new HystrixCodingPropertySource();
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;

    }

    /**
     * 如果没有设置hystrix的开关则默认开启
     */
    private void enableFeignHystrixIfNessary() {
        String key = "feign.hystrix.enabled";
        if (!environment.containsProperty(key)) {
            System.setProperty(key, "true");
        }
    }

    /**
     * 重新设置hystrix默认回退方法的信号量，默认10，由于框架默认提供的回退方法对高并发没有特别的限制，故设置默认值为1000
     */
    private void setDefaultHystrixFallbackSemaphoreMaxConcurrentRequestsIfNessary() {
        String key = "hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests";
        if (!environment.containsProperty(key)) {
            System.setProperty(key, "1000");
        }
    }

}
